package gates;

import java.awt.Graphics;

import master.QuantumRegister;

/**
 * 
 * @author Matthew & Oliver
 * 
 * The number of iterations is calculated in the apply method before the iterate is called
 * 
 * Grovers Algorithm, used for amplitude amplification or searching an unordered list, requires 4 steps
 * 1 - apply Oracle
 * 2 - apply Hadamard Gate to every qubit
 * 3 - apply Condition phase shift to register
 * 4 - apply Hadamard Gate to every qubit
 *
 * When a measurement is taken, will return the searched for state with very high probability.
 * 
 * It is worth pointing out, this is a grover iterator, rather than the gate, the gate itself
 * is all encoded in the loop in actOnReg method
 *
 */

public class Grover extends QuantumGate {
	
	private int iterations;
	QuantumGate oracle, conditionalS;
	FullHadamard H;
	
	
	
	public Grover(int search, int start){
		oracle = new Oracle(search);
		conditionalS = new CondPhaseShift(start);

		H = new FullHadamard();
	
	}


	public void actOnReg(QuantumRegister register) {
		
		
		//This calculates the number of iterations the algorithm must perform
		 
		this.iterations = (int)((Math.PI/4) * Math.round(Math.sqrt(register.getDimension())));

		
		for (int i = 0; i <iterations; i ++){

			
			
			//The gate starts here, and is inside the loop that applies the gate many times
			
			//step 1 - apply oracle
			oracle.actOnReg(register);
			//System.out.println("Step 1");
			//register.seeRegister();
			
			//Step 2- Apply hadamard gate to every qubit
			H.actOnReg(register);
			//System.out.println("Step 2");
			//register.seeRegister();
			
			
			//Step 3 - Apply conditional phase shift to every qubit bar 0
			conditionalS.actOnReg(register);
			//System.out.println("Step 3");
			//register.seeRegister();
			
			
			//step 4 - Apply hadamard gate to every qubit
			H.actOnReg(register);
			
			//System.out.println("Step 4");
			//register.seeRegister();
			
		}
		
	}





	@Override
	public int[] getActingBits() {
		int[] a = new int[1];
		a[0] = -1;
		return a;
	}
	
}
